/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package uk.ac.staffs.student.autopilot;

import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import java.util.Enumeration;

import org.apache.log4j.Logger;

import uk.ac.staffs.student.autopilot.packet.PacketBuilder;
import uk.ac.staffs.student.autopilot.views.APHciSwingPanel;

/**
 * 
 * @author Peter
 */
public class SerialPortManager {

    protected SerialPort serialPort;
    private PacketBuilder packetBuilder;
    public static Logger logger = Logger.getLogger(SerialPortManager.class);
    /**
     * The port we're normally going to use.
     */
    private static final String PORT_NAMES[] = { "COM2", // Windows
            "COM3", // Windows
            "COM4", // Windows
            "COM5", // Windows
            "COM6", // Windows
            "COM7", // Windows
    };

    /**
     * Milliseconds to block while waiting for port open
     */
    private static final int TIME_OUT = 2000;
    /**
     * Default bits per second for COM port.
     */
    private static final int DATA_RATE = 19200;
    /**
     * 
     */
    private APHciSwingPanel autoPilot;

    private CommPortIdentifier portId;

    public SerialPortManager() {
        this.initialize();
    }

    public SerialPortManager(final APHciSwingPanel autoPilot) {
        this.autoPilot = autoPilot;
        this.initialize();
    }

    protected PacketBuilder initialize() {

        packetBuilder = new PacketBuilder(this);

        final Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();

        // iterate through, looking for the port
        CommPortIdentifier currPortId = null;

        while (portEnum.hasMoreElements()) {
            currPortId = (CommPortIdentifier) portEnum.nextElement();
            for (final String portName : PORT_NAMES) {
                if (currPortId.getName().equals(portName)) {
                    portId = currPortId;
                    logger.info("Opened port: " + portId.getName());
                    break;
                }
            }
        }

        if (getPortId() == null) {
            logger.error("Could not find a useable COM port.");
            return null;
        }

        try {
            // open serial port, and use class name for the appName.
            serialPort = (SerialPort) getPortId().open("AutoPilot", TIME_OUT);

            // set port parameters
            serialPort.setSerialPortParams(DATA_RATE, SerialPort.DATABITS_8,
                    SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
            // open the streams
            getPacketBuilder().setInput(serialPort.getInputStream());
            getPacketBuilder().setOutput(serialPort.getOutputStream());
            //logger.error("Im here just before evenlistener");

            serialPort.addEventListener(getPacketBuilder());
            serialPort.notifyOnDataAvailable(true);

        } catch (final Exception e) {
            logger.error(e);
        }
        //logger.error("Im here just a but further");
        return getPacketBuilder();
    }

    /**
     * This should be called when you stop using the port. This will prevent
     * port locking on platforms like Linux.
     */
    public synchronized void close() {
        if (serialPort != null) {
            serialPort.removeEventListener();
            serialPort.close();
        }
    }

    /**
     * Returns the status of the serial port not sure about isRI() call but used
     * it for testing
     * 
     * @return
     */
    public SerialPortStatus getPortStatus() {
        final SerialPortStatus status = new SerialPortStatus(
                serialPort.getName(), serialPort.getBaudRate(),
                serialPort.isRI());

        return status;
    }

    /**
     * @return the portId
     */
    public CommPortIdentifier getPortId() {
        return portId;
    }

    /**
     * @return the packetBuilder
     */
    public PacketBuilder getPacketBuilder() {
        return packetBuilder;
    }

}
